package com.ideaaedi.springcloud.jd.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Sets;
import com.ideaaedi.springcloud.jd.commonds.constant.BaseConstant;
import com.ideaaedi.springcloud.jd.commonds.entity.PageInfo;
import com.ideaaedi.springcloud.jd.commonds.entity.user.bo.ApiInfoBO;
import com.ideaaedi.springcloud.jd.commonds.enums.user.ApiTypeEnum;
import com.ideaaedi.springcloud.jd.commonds.entity.user.po.SysApiResourcePO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.po.SysRoleApiRePO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.req.SysApiResourceListReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.req.SysRoleBindApiReqVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysApiResourceDetailRespVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysApiResourceListRespVO;
import com.ideaaedi.springcloud.jd.commonds.entity.user.vo.resp.SysQueryUserRoleRespVO;
import com.ideaaedi.springcloud.jd.commonspring.mapper.SysApiResourceMapper;
import com.ideaaedi.springcloud.jd.commonspring.mybatisplus.ServiceImplExt;
import com.ideaaedi.springcloud.jd.user.service.SysApiResourceService;
import com.ideaaedi.springcloud.jd.user.service.SysRoleApiReService;
import com.ideaaedi.springcloud.jd.user.service.SysUserService;
import org.springframework.beans.BeanUtils;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统-api资源 服务实现类
 * </p>
 *
 * @author <font size = "20" color = "#3CAA3C"><a href="https://gitee.com/JustryDeng">JustryDeng</a></font> <img src="https://gitee.com/JustryDeng/shared-files/raw/master/JustryDeng/avatar.jpg" />
 * @since 2021.0.5.B
 */
@Service
public class SysApiResourceServiceImpl extends ServiceImplExt<SysApiResourceMapper, SysApiResourcePO> implements SysApiResourceService {

    @Resource
    private SysRoleApiReService sysRoleApiReService;
    
    @Resource
    private SysUserService sysUserService;
    
    @Nullable
    @Override
    public SysApiResourceDetailRespVO detail(Long id) {
        Objects.requireNonNull(id, "id cannot be null.");
        SysApiResourcePO po = getById(id);
        if (po == null) {
            return null;
        }
        SysApiResourceDetailRespVO resp = new SysApiResourceDetailRespVO();
        BeanUtils.copyProperties(po, resp);
        return resp;
    }
    
    @Override
    public PageInfo<SysApiResourceListRespVO> list(SysApiResourceListReqVO req) {
        int pageNum = req.getPageNum();
        int pageSize = req.getPageSize();
        String name = req.getName();
        String path = req.getPath();
        String microService = req.getMicroService();
        Set<Long> apiIdSet = req.getApiIdSet();
        List<ApiTypeEnum> typeList = req.getTypeList();
        Set<Long> idSet = req.getIdSet();
    
        // 分页查
        IPage<SysApiResourcePO> pageInfo = new Page<>(pageNum, pageSize);
        IPage<SysApiResourcePO> page = this.baseMapper.selectPage(pageInfo,
                new LambdaQueryWrapper<SysApiResourcePO>()
            .in(!CollectionUtils.isEmpty(idSet), SysApiResourcePO::getId, idSet)
            .eq(microService != null && microService.trim().length() != 0,  SysApiResourcePO::getMicroService, microService)
            .in(!CollectionUtils.isEmpty(apiIdSet),  SysApiResourcePO::getId, apiIdSet)
            .in(!CollectionUtils.isEmpty(typeList),  SysApiResourcePO::getType, typeList)
            .like(path != null && path.trim().length() != 0,  SysApiResourcePO::getPath, path)
            .like(name != null && name.trim().length() != 0,  SysApiResourcePO::getName, name)
            .orderByDesc(SysApiResourcePO::getId)
        );
        // 转换为resp模型
        List<SysApiResourcePO> records = page.getRecords();
        List<SysApiResourceListRespVO> list;
        if (CollectionUtils.isEmpty(records)) {
            list = Collections.emptyList();
        } else {
            list = records.stream().map(po -> {
                SysApiResourceListRespVO resp = new SysApiResourceListRespVO();
                BeanUtils.copyProperties(po, resp);
                return resp;
            }).collect(Collectors.toList());
        }
        return PageInfo.of(page.getTotal(), pageNum, pageSize, list);
    }
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<SysApiResourceListRespVO> bindApi(SysRoleBindApiReqVO req) {
        Long roleId = req.getRoleId();
        Set<Long> apis = req.getApis();
        // 删除原来的
        sysRoleApiReService.remove(new LambdaQueryWrapper<SysRoleApiRePO>()
                .eq(SysRoleApiRePO::getRoleId, roleId)
        );
        
        // 添加新的
        if (!CollectionUtils.isEmpty(apis)) {
            List<SysRoleApiRePO> list = apis.stream().map(menuId -> {
                SysRoleApiRePO re = new SysRoleApiRePO();
                re.setId(IdWorker.getId());
                re.setApiId(menuId);
                re.setRoleId(roleId);
                return re;
            }).collect(Collectors.toList());
            sysRoleApiReService.saveBatch(list);
        }
        return queryApi(Sets.newHashSet(roleId));
    }
    
    @Override
    public List<SysApiResourceListRespVO> queryApi(@Nullable Set<Long> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            return Collections.emptyList();
        }
        Set<Long> apiIdSet = this.baseMapper.selectApiIdByRoleIds(roleIds);
        if (CollectionUtils.isEmpty(apiIdSet)) {
            return Collections.emptyList();
        }
        SysApiResourceListReqVO req = new SysApiResourceListReqVO();
        req.setApiIdSet(apiIdSet);
        req.setPageSize(BaseConstant.IGNORE_PAGING);
        return list(req).getDataList();
    }
    
    @Override
    public LinkedHashSet<ApiInfoBO> listUserApi(Long userId) {
        List<SysQueryUserRoleRespVO> sysQueryUserRoleRespList = sysUserService.queryRole(userId);
        if (CollectionUtils.isEmpty(sysQueryUserRoleRespList)) {
            return new LinkedHashSet<>();
        }
        return queryApiSimplify(sysQueryUserRoleRespList.stream().map(SysQueryUserRoleRespVO::getId).collect(Collectors.toSet()));
    }
    
    @Override
    public LinkedHashSet<ApiInfoBO> queryApiSimplify(@Nullable Set<Long> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            return new LinkedHashSet<>();
        }
        Set<ApiInfoBO> apis = this.baseMapper.selectApiByRoleIds(roleIds);
        return apis.stream()
                .sorted(Comparator.comparing(ApiInfoBO::getPath))
                .collect(Collectors.toCollection(LinkedHashSet::new));
    }
}
